package com.amkai.aes.webservice.binary.objecthandler.diee;

import java.io.Serializable;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.hibernate.Query;

import com.amkai.aes.aescommon.diee.parameters.DIEEParameterStoreData;
import com.amkai.aes.aescommon.service.diee.DIEECommonUtils;
import com.amkai.aes.aescommon.service.diee.DIEEReportTaskJob;
import com.amkai.aes.aescommon.service.diee.DIEEReportTaskResult;
import com.amkai.aes.generatedbeans.diee.ParameterStoreKind;
import com.amkai.aes.generatedbeans.diee.ReportGroup;
import com.amkai.aes.generatedbeans.diee.ReportTask;
import com.amkai.aes.generatedbeans.organization.Department;
import com.amkai.aes.generatedbeans.passport.Passport;
import com.amkai.aes.server.diee.DIEEParameterManager;
import com.amkai.aes.server.diee.DIEEReportGroupValidator;
import com.amkai.aes.server.diee.DIEEServerUtils;
import com.amkai.aes.server.diee.IReportGroupValidator;
import com.amkai.common.extensions.hibernate.config.manager.SessionManager;
import com.amkai.diee.utils.DIEEDebugger;

public class DIEEReportTaskHandler extends AbstractDIEEHandler<DIEEReportTaskJob, DIEEReportTaskResult> {
	
	private final Comparator<ReportGroup> reportGroupComparator = new Comparator<ReportGroup>() {
		@Override
		public int compare(ReportGroup o1, ReportGroup o2) {
			int i = DIEECommonUtils.compare(o1.getSortOrder(), o2.getSortOrder());
			if (i==0)
				return DIEECommonUtils.compare(o1.getName(), o2.getName());
			else
				return i;
		}
	};
	
	private final Comparator<ReportTask> reportTaskComparator = new Comparator<ReportTask>() {
		@Override
		public int compare(ReportTask o1, ReportTask o2) {
			int i = DIEECommonUtils.compare(o1.getSortOrder(), o2.getSortOrder());
			if (i==0)
				return DIEECommonUtils.compare(o1.getName(), o2.getName());
			else
				return i;
		}
	};
	
	@Override
	protected DIEEReportTaskResult createResult() {
		return new DIEEReportTaskResult();
	}
	
	@Override
	protected String getName() {
		return "DIEE REPORT TASK JOB";
	}
	
	@Override
	public void process(DIEEReportTaskJob job, Serializable object, DIEEReportTaskResult result, SessionManager sessionManager, DIEEDebugger debugger) throws Exception, Error {
		Department department = job.getModuleDepartment();
		if (department!=null)
			department = (Department)sessionManager.execute("from Department as x where x.id=:id").setLong("id", department.getId()).uniqueResult();
		if (department==null) {
			error("Can't find module department!");
		} else {
			info("Department: " + department.getName());
		}
		Passport passport = null;
		if (job.getPassportId()!=null) {
			passport = sessionManager.get(Passport.class, job.getPassportId());
			info("Passport: " + (passport==null ? "<not found>" : passport.getName()));
		}
		Long groupId = job.getGroupId();
		String sysId = job.getGroupSysId();
		if (job.isQueryReportGroups()) {
			if (groupId!=null || sysId!=null) {
				Query query;
				if (groupId!=null) {
					info("Query the report groups with id #"+groupId+"...");
					query = sessionManager.execute("from ReportGroup as g where g.id=:id").setLong("id", groupId);
				} else {
					info("Query the report groups with sysid '"+sysId+"'...");
					query = sessionManager.execute("from ReportGroup as g where g.sysId=:id").setString("id", sysId);
				}
				setReportGroups(result, query.list(), new DIEEReportGroupValidator(department));
			}
		} else if (job.isQueryChildGroups()) {
			if (groupId==null && sysId==null) {
				info("Query the root report groups...");
			} else if (groupId!=null) {
				info("Query the child report groups of group #"+groupId+"...");
			} else {
				info("Query the child report groups of group '"+sysId+"'...");
			}
			List<ReportGroup> groups = DIEEServerUtils.queryReportGroups(sessionManager, (groupId==null ? sysId : groupId), new DIEEReportGroupValidator(department));
			setReportGroups(result, groups, null);
		}
		if (job.isQueryChildTasks() && (groupId!=null || sysId!=null)) {
			List<ReportTask> tasks = DIEEServerUtils.queryReportTasks(sessionManager, (groupId==null ? sysId : groupId), department);
			if (tasks!=null) {
				for (ReportTask task : tasks) {
					DIEEServerUtils.initReportTask(task);
				}
				info("Count: "+tasks.size());
			} else {
				info("Count: 0");
			}
			Collections.sort(tasks, reportTaskComparator);
			result.setReportTasks(tasks);
		}
		// AES-11650, AES-12131
		List<DIEEParameterStoreData> parameterStoreData = job.getParameterStoreData();
		if (parameterStoreData!=null) {
			info("Handle parameter store...");
			DIEEParameterManager manager = new DIEEParameterManager(sessionManager, department, passport);
			for (DIEEParameterStoreData data : parameterStoreData) {
				if (data.isLoaded()) {
					info("\tload parameter: " + data.getName());
					if (data.getUniqueId()==null && data.getAuditTrailReportPropertiesId()==null)
						warn("\t\tunique id and audit trail report properties id is empty");
				} else {
					info("\tsave parameter: " + data.getName() + ": " + getArrayValueString(data.getValues()));
					if (data.getUniqueId()==null)
						warn("\t\tunique id is empty");
				}
				manager.register(data);
			}
			sessionManager.openTransaction();
			try {
				manager.process();
				sessionManager.commitTransaction();
			} catch (Exception e) {
				sessionManager.rollbackTransaction();
				throw e;
			}
			for (DIEEParameterStoreData data : manager.getParameters()) {
				result.addStoredParameterValue(data);
			}
		}
		// AES-11606
		if (job.getStoredParameterKindToQuery()!=null) {
			ParameterStoreKind kind = job.getStoredParameterKindToQuery();
			if (kind!=null) {
				info("Query stored parameter unique ids for "+kind+"...");
				result.setStoredParameterUniqueIDs(
				sessionManager.execute(
						"select distinct p.uniqueId from ParameterStore as p " +
						"where p.kindWrapper.id = " + kind.ordinal() +
						" and p.department.id = " + department.getId() +
						" order by p.uniqueId"
					).list());
			} else {
				warn("Cannot query stored parameter unique ids: kind is empty.");
			}
		}
	}
	
	private final String getReportTaskUniqueId(Long id, String uniqueId, SessionManager sessionManager) {
		if (uniqueId==null) {
			if (id!=null) {
				uniqueId = DIEEServerUtils.getReportTaskUniqueId(sessionManager, id);
			}
		}
		return uniqueId;
	}
	
	private final void setReportGroups(DIEEReportTaskResult result, List<ReportGroup> groups, IReportGroupValidator validator) {
		if (groups!=null) {
			info("Count: "+groups.size());
			if (validator!=null) {
				for (int i=groups.size()-1; i>=0; i--) {
					ReportGroup group = groups.get(i);
					if (!validator.isValid(group)) {
						groups.remove(i);
					}
				}
			}
		} else {
			info("Count: 0");
		}
		Collections.sort(groups, reportGroupComparator);
		result.setReportGroups(groups);
	}
	
}
